/**
 * Copyright (c) [2025] [AGIROS] 
 * [travoddsgen] is licensed under Mulan PSL v2. 
 * You can use this software according to the terms and conditions of the Mulan PSL v2. 
 * You may obtain a copy of Mulan PSL v2 at: 
 *          http://license.coscl.org.cn/MulanPSL2 
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 
 * See the Mulan PSL v2 for more details.
 */ 

#include <iostream>
#include "CppLangSerializeKeyVisitor.h"
#include "CLangTypeNameVisitor.h"

CppLangSerializeKeyVisitor::CppLangSerializeKeyVisitor(CppLangTypeNameVisitor* typeNameVisitor)
    : FileGenVisitor("", ""), typeNameVisitor_(typeNameVisitor), isArray_(false), plainCdrMode_(true) {
    CLangTypeNameVisitor* clangTypeNameVisitor = dynamic_cast<CLangTypeNameVisitor*>(typeNameVisitor_);
    isCppLangTypeSupport_ = (clangTypeNameVisitor == nullptr);
}

void CppLangSerializeKeyVisitor::visit(BaseTypeNode& node) {
    if (isArray_) {
        std::string memberTypeName = typeNameVisitor_->findName(memberType_);
        content_ += indent() + "if (!cdr->serializeBaseTypeArray(";
        content_ += "(" + memberTypeName + "*)";
        content_ += memberName_ + ", sizeof(" + memberName_ + ") / sizeof(" + memberTypeName + "))) {\n";
        ++indentLevel_;
        content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
        content_ += indent() + "return -1;\n";
        --indentLevel_;
        content_ += indent() + "}\n";
        return;
    }
    // 非数组
    content_ += indent() + "if (!cdr->serializeBaseType(" + memberName_ + ")) {\n";
    ++indentLevel_;
    content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
    content_ += indent() + "return -1;\n";
    --indentLevel_;
    content_ += indent() + "}\n";
}

void CppLangSerializeKeyVisitor::visit(SequenceTypeNode &node) {
    // 序列化vector的长度
    content_ += indent() + "if (!cdr->serializeBaseType(" + memberName_ + ".size())) {\n";
    ++indentLevel_;
    content_ += indent() + "fprintf(stderr, \"Serialization length failed for field: " + memberName_ + "\\n\");\n";
    content_ += indent() + "return -1;\n";
    --indentLevel_;
    content_ += indent() + "}\n";
    // 序列化vector的内容
    // 如果elementType是BaseTypeNode，调用serializeBaseTypeArray
    BaseTypeNode *eleType = dynamic_cast<BaseTypeNode *>(node.type_);
    std::string memberTypeName = typeNameVisitor_->findName(memberType_);
    if (eleType) {
        content_ += indent() + "if (!cdr->serializeBaseTypeArray(" + memberName_ + ".data(), " + memberName_ + ".size())) {\n";
        ++indentLevel_;
        content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
        content_ += indent() + "return -1;\n";
        --indentLevel_;
        content_ += indent() + "}\n";
        return;
    }
    // 其他情况，循环调用elementType的序列化visitor
    content_ += indent() + "for (size_t i = 0; i < " + memberName_ + ".size(); ++i) {\n";
    memberName_ = memberName_ + "[i]";
    ++indentLevel_;
    node.type_->accept(*this);
    --indentLevel_;
    content_ += indent() + "}\n";
}

void CppLangSerializeKeyVisitor::visit(StringTypeNode& node) {
    if (isArray_) {
        // 如果是数组类型，循环调用serializeString函数
        content_ += indent() + "for (size_t i = 0; i < sizeof(" + memberName_ + ") / sizeof(" + memberName_ + "[0]); ++i) {\n";
        ++indentLevel_;
        content_ += indent() + "if (!cdr->serializeString(" + memberName_ + "[i])) {\n";
        ++indentLevel_;
        content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
        content_ += indent() + "return -1;\n";
        --indentLevel_;
        content_ += indent() + "}\n";
        --indentLevel_;
        content_ += indent() + "}\n";
        return;
    }
    content_ += indent() + "if (!cdr->serializeString(" + memberName_ + ")) {\n";
    ++indentLevel_;
    content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
    content_ += indent() + "return -1;\n";
    --indentLevel_;
    content_ += indent() + "}\n";
}

void CppLangSerializeKeyVisitor::visit(WideStringTypeNode& node) {
    if (isArray_) {
        // 如果是数组类型，循环调用serializeString函数
        content_ += indent() + "for (size_t i = 0; i < sizeof(" + memberName_ + ") / sizeof(" + memberName_ + "[0]); ++i) {\n";
        ++indentLevel_;
        content_ += indent() + "if (!cdr->serializeWString(" + memberName_ + "[i])) {\n";
        ++indentLevel_;
        content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
        content_ += indent() + "return -1;\n";
        --indentLevel_;
        content_ += indent() + "}\n";
        --indentLevel_;
        content_ += indent() + "}\n";
        return;
    }
    content_ += indent() + "if (!cdr->serializeWString(" + memberName_ + ")) {\n";
    ++indentLevel_;
    content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
    content_ += indent() + "return -1;\n";
    --indentLevel_;
    content_ += indent() + "}\n";
}

void CppLangSerializeKeyVisitor::visit(FixedPtTypeNode& node) {
    if (node.digits_) {
        node.digits_->accept(*this);
    }
    if (node.scale_) {
        node.scale_->accept(*this);
    }
}

void CppLangSerializeKeyVisitor::visit(MapTypeNode& node) {
    // 序列化map的长度
    content_ += indent() + "if (!cdr->serializeBaseType(" + memberName_ + ".size())) {\n";
    ++indentLevel_;
    content_ += indent() + "fprintf(stderr, \"Serialization length failed for field: " + memberName_ + "\\n\");\n";
    content_ += indent() + "return -1;\n";
    --indentLevel_;
    content_ += indent() + "}\n";
    // 序列化map的内容
    content_ += indent() + "for (auto& pair : " + memberName_ + ") {\n";
    ++indentLevel_;
    // 序列化key
    memberName_ = "pair.first";
    memberType_ = node.keyType_;
    isArray_ = false;
    if (node.keyType_) {
        node.keyType_->accept(*this);
    }
    // 序列化value
    memberName_ = "pair.second";
    memberType_ = node.valueType_;
    isArray_ = false;
    if (node.valueType_) {
        node.valueType_->accept(*this);
    }
    --indentLevel_;
    content_ += indent() + "}\n";
}

void CppLangSerializeKeyVisitor::visit(StructDefNode& node) {
    // 每次清空content_，重新生成
    content_ = "";
    std::string structName = typeNameVisitor_->findName(&node);
    // 如果已经生成则略过
    if (generatedTypeNames.find(structName) != generatedTypeNames.end()) {
        return;
    }
    generatedTypeNames[structName] = 0;
    bool isNested = (TypeAnnotationNode::getExtensibility(node.annotations_) == TypeAnnotationNode::AnnotationType::MUTABLE);
    plainCdrMode_ = true;
    content_ += "int " + structName + "TypeSupport::serialize_key(void* data, AGIDDSCdrSerializer* cdr, int endian) {\n";
    ++indentLevel_;
    content_ += indent() + structName + "* structData = static_cast<" + structName + "*>(data);\n";
    content_ += indent() + "bool memberHasKey = false;\n";
    if (isNested) {
        plainCdrMode_ = false;
        content_ += indent() + "bool useExtend = true;\n";
        content_ += indent() + "char* lenAddr = nullptr;\n";
        content_ += indent() + "unsigned int beforeLen = 0;\n";
        content_ += indent() + "unsigned int afterLen = 0;\n";
    }
    // 处理继承
    if (node.parent_) {
        if (isCppLangTypeSupport_) {
            std::string parentTypeName = typeNameVisitor_->findName(node.parent_);
            content_ += indent() + "if (" + parentTypeName + "TypeSupport::get_instance()->serialize_data((void*)dynamic_cast<" + parentTypeName + "*>(structData), cdr, endian) != 0) {\n";
            ++indentLevel_;
            content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
            content_ += indent() + "return -1;\n";
            --indentLevel_;
            content_ += indent() + "}\n";
        } else {
            std::string parentTypeName = typeNameVisitor_->findName(node.parent_);
            content_ += indent() + "if (" + parentTypeName + "TypeSupport::get_instance()->serialize_data((void*)(&structData->parent), cdr, endian) != 0) {\n";
            ++indentLevel_;
            content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
            content_ += indent() + "return -1;\n";
            --indentLevel_;
            content_ += indent() + "}\n";
        }
    }
    for (auto &member : node.members_->nodes_) {
        member->accept(*this);
    }
    content_ += indent() + "return 0;\n";
    --indentLevel_;
    content_ += "}\n\n";
    return;
}

void CppLangSerializeKeyVisitor::visit(ScopedNameNode &node) {
    DefinitionNode *eleTypeDcl = typeNameVisitor_->findType(&node);
    TypeDefDclNode* eleTypeDef = dynamic_cast<TypeDefDclNode*>(eleTypeDcl);
    if (eleTypeDef) {
        isArray_ = (eleTypeDef->dims_ != nullptr && eleTypeDef->dims_->nodes_.size() > 0);
        memberType_ = eleTypeDef->refType_;
        eleTypeDef->refType_->accept(*this);
        return;
    }
    EnumDclNode* eleEnum = dynamic_cast<EnumDclNode*>(eleTypeDcl);
    if (eleEnum) {
        eleEnum->accept(*this);
        return;
    }
    std::string memberTypeName = "";
    StructDefNode* eleStruct = dynamic_cast<StructDefNode*>(eleTypeDcl);
    if (eleStruct) {
        memberTypeName = typeNameVisitor_->findName(eleStruct);
    }
    UnionDefNode* eleUnion = dynamic_cast<UnionDefNode*>(eleTypeDcl);
    if (eleUnion) {
        memberTypeName = typeNameVisitor_->findName(eleUnion);
    }
    content_ += indent() + "memberHasKey = " + memberTypeName + "TypeSupport::get_instance()->has_key();\n";
    if (isArray_) {
        content_ += indent() + "for (size_t i = 0; i < sizeof(" + memberName_ + ") / sizeof(" + memberName_ + "[0]); ++i) {\n";
        // 如果嵌套的struct或union含有key成员，递归调用serialize_key
        content_ += indent() + "if (memberHasKey) {\n";
        ++indentLevel_;
        content_ += indent() + "if (" + memberTypeName + "TypeSupport::get_instance()->serialize_key((void*)" + "(" + memberTypeName + "*)" + "(" + memberName_ + ")[i], cdr, endian) != 0) {\n";
        ++indentLevel_;
        content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "[i]\\n\");\n";
        content_ += indent() + "return -1;\n";
        --indentLevel_;
        content_ += indent() + "}\n";
        --indentLevel_;
        // 嵌套的struct或union不含有key成员，调用serialize_data
        content_ += indent() + "} else {\n";
        ++indentLevel_;
        content_ += indent() + "if (" + memberTypeName + "TypeSupport::get_instance()->serialize_data(" + "(" + memberTypeName + "*)" + "(" + memberName_ + ")[i], cdr, endian) != 0) {\n";
        ++indentLevel_;
        content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "[i]\\n\");\n";
        content_ += indent() + "return -1;\n";
        --indentLevel_;
        content_ += indent() + "}\n";
        --indentLevel_;
        content_ += indent() + "}\n";
        return;
    }
    // 如果嵌套的struct或union含有key成员，递归调用serialize_key
    content_ += indent() + "if (memberHasKey) {\n";
    ++indentLevel_;
    content_ += indent() + "if (" + memberTypeName + "TypeSupport::get_instance()->serialize_key((void*)&" + memberName_ + ", cdr, endian) != 0) {\n";
    ++indentLevel_;
    content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
    content_ += indent() + "return -1;\n";
    --indentLevel_;
    content_ += indent() + "}\n";
    --indentLevel_;
    // 嵌套的struct或union不含有key成员，调用serialize_data
    content_ += indent() + "} else {\n";
    ++indentLevel_;
    content_ += indent() + "if (" + memberTypeName + "TypeSupport::get_instance()->serialize_data(&" + memberName_ + ", cdr, endian) != 0) {\n";
    ++indentLevel_;
    content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
    content_ += indent() + "return -1;\n";
    --indentLevel_;
    content_ += indent() + "}\n";
    --indentLevel_;
    content_ += indent() + "}\n";
}

void CppLangSerializeKeyVisitor::visitPlCdr(ASTNode* type, const std::string& idStr) {
    // 序列化parameter头，包括id和长度
    content_ += indent() + "useExtend = true;\n";
    content_ += indent() + "lenAddr = cdr->serializeParameterHeader(useExtend, true, ";
    // member id
    content_ += idStr;
    content_ += ");\n";
    // 错误处理
    content_ += indent() + "if (!lenAddr) {\n";
    ++indentLevel_;
    content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
    content_ += indent() + "return -1;\n";
    --indentLevel_;
    content_ += indent() + "}\n";
    // 获取序列化数据前的空间大小
    content_ += indent() + "beforeLen = cdr->getRemainingSpace();\n";
    // 序列化成员
    type->accept(*this);
    // 回填长度，先获取序列化数据后的空间大小，再调用parameterLenSerializeKey函数
    content_ += indent() + "afterLen = cdr->getRemainingSpace();\n";
    content_ += indent() + "cdr->parameterLenSerialize(lenAddr, beforeLen - afterLen, useExtend ? 4 : 2);\n";  
}

void CppLangSerializeKeyVisitor::visit(MemberNode &node) {
    // TODO 先不处理shared成员
    if (node.isShared()) {
        return;
    }
    // 仅处理key成员
    if (!node.isKey()) {
        return;
    }
    // 当前成员为key成员
    memberName_ = "structData->" + *node.identifier_;
    memberType_ = node.type_;
    isArray_ = node.arrayDims_ && node.arrayDims_->nodes_.size() > 0;
    if (plainCdrMode_) {
        node.type_->accept(*this);
        return;
    }
    // PL_CDR模式
    PositiveIntConstNode* id = node.getIdNode();
    if (!id) {
        // mutable类型的成员必须有id
        std::cerr << "Error: mutable member " << *(node.identifier_) << "::" << *(node.identifier_) << " must have id" << std::endl;
        exit(1);
    }
    std::string idStr = typeNameVisitor_->findName(id);
    memberName_ = "structData->" + *node.identifier_;
    visitPlCdr(node.type_, idStr);
}

void CppLangSerializeKeyVisitor::visit(ListNode<FixedArraySizeNode *> &node) {
    for (auto &fixedArraySize : node.nodes_) {
        if (fixedArraySize) {
            fixedArraySize->accept(*this);
        }
    }
}

void CppLangSerializeKeyVisitor::visit(FixedArraySizeNode& node) {
    if (node.size_) {
        node.size_->accept(*this);
    }
}

void CppLangSerializeKeyVisitor::visit(UnionDefNode& node) {
    // 每次清空content_，重新生成
    content_ = "";
    std::string unionName = typeNameVisitor_->findName(&node);
    // 如果已经生成则略过
    if (generatedTypeNames.find(unionName) != generatedTypeNames.end()) {
        return;
    }
    generatedTypeNames[unionName] = 0;
    bool isNested = (TypeAnnotationNode::getExtensibility(node.annotations_) == TypeAnnotationNode::AnnotationType::MUTABLE);
    content_ += "int " + unionName + "TypeSupport::serialize_key(void* data, AGIDDSCdrSerializer* cdr, int endian) {\n";
    ++indentLevel_;
    content_ += indent() + unionName + "* structData = static_cast<" + unionName + "*>(data);\n";
    plainCdrMode_ = true;
    if (isNested) {
        plainCdrMode_ = false;
        content_ += indent() + "bool useExtend = true;\n";
        content_ += indent() + "char* lenAddr = nullptr;\n";
        content_ += indent() + "unsigned int beforeLen = 0;\n";
        content_ += indent() + "unsigned int afterLen = 0;\n";
    }
    // 序列化辨别器的值
    if (node.switchType_->key_) {
        memberName_ = "structData->u_";
        isArray_ = false;
        if (plainCdrMode_) {
            if (node.switchType_->type_) {
                memberType_ = node.switchType_->type_;
                node.switchType_->type_->accept(*this);
            } else if (node.switchType_->scopedName_) {
                memberType_ = node.switchType_->scopedName_;
                node.switchType_->scopedName_->accept(*this);
            }
        } else {
            if (node.switchType_->type_) {
                memberType_ = node.switchType_->type_;
                visitPlCdr(node.switchType_->type_, "0");
            } else if (node.switchType_->scopedName_) {
                memberType_ = node.switchType_->scopedName_;
                visitPlCdr(node.switchType_->scopedName_, "0");
            }
        }
    }
    // union只允许辨别器为key
    content_ += indent() + "return 0;\n";
    --indentLevel_;
    content_ += "}\n\n";
    return;
}

void CppLangSerializeKeyVisitor::visit(EnumDclNode& node) {

    std::string bitBound = typeNameVisitor_->getBitbound(node);
    // 是否为数组
    if (isArray_) {
        content_ += indent() + "for (size_t i = 0; i < sizeof(" + memberName_ + ") / sizeof(" + memberName_ + "[0]); ++i) {\n";
        ++indentLevel_;
        memberName_ = memberName_ + "[i]";
    }
    content_ += indent() + "switch(" + bitBound + " / 8) {\n";
    ++indentLevel_;
    content_ += indent() + "case 1:\n";
    ++indentLevel_;
    content_ += indent() + "if (!cdr->serializeBaseType(static_cast<char>(" + memberName_ + "))) {\n";
    ++indentLevel_;
    content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
    content_ += indent() + "return -1;\n";
    --indentLevel_;
    content_ += indent() + "}\n";
    content_ += indent() + "break;\n";
    --indentLevel_;
    content_ += indent() + "case 2:\n";
    ++indentLevel_;
    content_ += indent() + "if (!cdr->serializeBaseType(static_cast<short>(" + memberName_ + "))) {\n";
    ++indentLevel_;
    content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
    content_ += indent() + "return -1;\n";
    --indentLevel_;
    content_ += indent() + "}\n";
    content_ += indent() + "break;\n";
    --indentLevel_;
    content_ += indent() + "case 4:\n";
    ++indentLevel_;
    content_ += indent() + "if (!cdr->serializeBaseType(static_cast<int>(" + memberName_ + "))) {\n";
    ++indentLevel_;
    content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
    content_ += indent() + "return -1;\n";
    --indentLevel_;
    content_ += indent() + "}\n";
    content_ += indent() + "break;\n";
    --indentLevel_;
    content_ += indent() + "default:\n";
    ++indentLevel_;
    content_ += indent() + "fprintf(stderr, \"Serialization failed for field: " + memberName_ + "\\n\");\n";
    content_ += indent() + "return -1;\n";
    content_ += indent() + "break;\n";
    --indentLevel_;
    content_ += indent() + "}\n";
    if (isArray_) {
        --indentLevel_;
        content_ += indent() + "}\n";
    }
}
